/*
 * Region.h
 * independence of the lcode
 * Created on: 2009-8-23
 *      Author: ws
 */

#ifndef REGION_H_
#define REGION_H_

#include<vector>
#include<stack>
#include<list>
#include<set>
#include<iostream>
#include"common.hpp"
#include"Value.hpp"
#include"Operand.hpp"
#include"Operation.hpp"
#include"NodeSequence.hpp"

#include"ScheduleTable.hpp"
class Dep;
class Node;
class CtrFlow;
class Region;
class InterfGraph;

template<unsigned int> class Operation;

class CtrFlow {
private:
	Region * from;
	Region * to;
	std::vector<int> live_regs;

	bool to_visisted;
	//the to_vlmap.size() == 0; means the to is not visited
	std::vector<std::pair<int, int> >  to_vlmap;
public:
	Region *get_from()const
	{
		return from;
	}
	Region *get_to()const
	{
		return to;
	}
	bool is_live(int id);
	CtrFlow(Region * from, Region * to);
	virtual ~CtrFlow();
};

/*
 * =====================================================
 *	Region
 * =====================================================
 */
class Region {
	friend class RegionBuilder;
private:
	enum BLKType type;
	int id;
	std::vector<CtrFlow*> inflows;
	std::vector<CtrFlow*> outflows;
	std::vector<int> live_in;
	Region *next;
	Region *prev;
	bool visited;

	/*================================
	 * for Region_builder
	 *===============================
	 */

	void init_schedule_table();
	//for region builder  call
	Region();
public:
	int get_id(){ return id;}
	enum BLKType get_type()const { return type;}
	Region* get_next()const
	{
		return next;
	}
	Region* get_prev()const
	{
		return prev;
	}

	std::vector<CtrFlow*>& get_outflows()
	{
		return outflows;
	}

	std::vector<CtrFlow*>& get_inflows()
	{
		return inflows;
	}

	std::vector<Region*> get_from_regions()
	{
		std::vector<Region*> regions;
		for(int i = 0; i < inflows.size(); i++)
		{
			regions.push_back(inflows[i]->get_from());
		}
		return regions;
	}
	std::vector<Region*> get_to_regions()
	{
		std::vector<Region*> regions;
		for(int i = 0; i < outflows.size(); i++)
		{
			regions.push_back(outflows[i]->get_to());
		}
		return regions;
	}

	bool is_visited()const;
	void set_visited();
	//virtual void schedule();
	virtual ~Region();
	typedef std::list<Dep*> DepSequence;

/*====================================================
 * this is used for calculate the dag_info
 *===================================================
 */
protected:
	Operation<START_NODE> * start_node;
	Operation<END_NODE> * end_node;
private:
	int schedule_lenth;
	NodeSequence  node_list;
	std::list<Dep*> dep_list;

	/*====================================================
 	*   for DEP
 	*====================================================
 	*/
   	void build_reg_deps(Node & x, enum LOC_Type tx, Node & y , enum LOC_Type ty);
	/* insert the new Dep to the DAG*/
	void build_new_dep(Node & from , location  from_loc, Node & to , location to_loc);

	void build_dag();
	static bool check_type_consistent(location from, location to, int dep_type);
	static location get_mem_loc(Node * n, int index);
public:
	void reset_visited_flag();

	//for cluster_assigne function so the no "const" semantic
	Operation<START_NODE> * get_start_node()const
	{
		return start_node;
	}
	Operation<END_NODE> * get_end_node()const
	{
		return end_node;
	}

	NIter NEnd(){ return node_list.end();}
	NIter NBegin(){return node_list.begin();}
/*
 * ==============================================================
 * 	interface for DAG information
 * ==============================================================
 */

	void build_du_chain();
	void calculate_dag_info(unsigned int flag_mask);
	void sort_indeps();
	int  get_schedule_lenth(){ return schedule_lenth;}
	void print()const;
/*===============================================================
 *interface for register allocate
 *===============================================================
 */
	void build_interference_graph(InterfGraph * graph);
};

#endif
